package com.hoppinzq.service.file;

import com.alibaba.fastjson.JSONArray;
import com.hoppinzq.service.aop.annotation.ApiMapping;
import com.hoppinzq.service.aop.annotation.ApiServiceMapping;
import com.hoppinzq.service.aop.annotation.RateLimit;
import com.hoppinzq.service.bean.SSHBean;
import com.hoppinzq.service.cache.SSHCache;
import com.hoppinzq.service.exception.ResultReturnException;
import com.hoppinzq.service.util.RedisUtils;
import com.hoppinzq.service.util.UUIDUtil;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ApiServiceMapping(title = "文件服务", description = "文件服务",roleType = ApiServiceMapping.RoleType.RIGHT)
public class FileService {

    @Autowired
    private RedisUtils redisUtils;

    @ApiMapping(value = "createFolder", title = "创建文件夹", description = "创建文件夹")
    public void createFolder(String foldername,String pdir) throws Exception {
        SSHBean sshBean= new SSHBean();
        sshBean.sshRemoteLogin();
        Session sshSession=sshBean.getSession();
        SSHCache.sshMap.put(UUIDUtil.getUUID(),sshBean);
        ChannelSftp channelSftp = (ChannelSftp) sshSession.openChannel("sftp");
        channelSftp.connect();
        String remoteDirPath = "/home/file/"+pdir;
        Vector<ChannelSftp.LsEntry> lsEntries = channelSftp.ls(remoteDirPath);
        boolean folderExists = false;
        for (ChannelSftp.LsEntry entry : lsEntries) {
            if (entry.getFilename().equals(foldername)) {
                folderExists = true;
                break;
            }
        }
        if (folderExists) {
            throw new RuntimeException("文件夹已存在，请重新命名文件夹");
        } else {
            //文件夹不存在，新建文件夹
            channelSftp.mkdir(remoteDirPath+"/"+foldername);
            redisUtils.del("manager:file_tree_"+remoteDirPath);
        }
    }

    @ApiMapping(value = "checkFile", title = "检查文件是否重复", description = "检查文件是否重复")
    public void checkFile(String filename,String pdir) throws Exception {
        SSHBean sshBean= new SSHBean();
        sshBean.sshRemoteLogin();
        Session sshSession=sshBean.getSession();
        SSHCache.sshMap.put(UUIDUtil.getUUID(),sshBean);
        ChannelSftp channelSftp = (ChannelSftp) sshSession.openChannel("sftp");
        channelSftp.connect();
        String remoteDirPath = "/home/file/"+pdir;
        Vector<ChannelSftp.LsEntry> lsEntries = channelSftp.ls(remoteDirPath);
        boolean fileExists = false;
        for (ChannelSftp.LsEntry entry : lsEntries) {
            if (entry.getFilename().equals(filename)) {
                fileExists = true;
                break;
            }
        }
        if (fileExists) {
            throw new RuntimeException(filename+" 文件已存在 /"+pdir+" 的文件夹中，确定覆盖？");
        }
    }

    @ApiMapping(value = "uploadfile", title = "文件上传", description = "文件上传",type = ApiMapping.Type.POST)
    public void uploadfile(MultipartFile file, String dir) throws Exception {
        SSHBean sshBean= new SSHBean();
        sshBean.sshRemoteLogin();
        Session sshSession=sshBean.getSession();
        SSHCache.sshMap.put(UUIDUtil.getUUID(),sshBean);
        ChannelSftp channelSftp = (ChannelSftp) sshSession.openChannel("sftp");
        channelSftp.connect();
        String remoteDirPath = "/home/file/"+dir;
        redisUtils.del("manager:file_tree_"+remoteDirPath);
        String dst = remoteDirPath+"/"+file.getOriginalFilename();
        channelSftp.put(file.getInputStream(), dst, ChannelSftp.OVERWRITE);
        channelSftp.exit();
        channelSftp.quit();
    }

    @ApiMapping(value = "showFile", title = "展示文件", description = "展示文件")
    public JSONArray showFile(String path) throws Exception {
        Pattern pattern = Pattern.compile("/\\.\\.|/\\.");
        Matcher matcher = pattern.matcher(path);
        while (matcher.find()) {
            throw new ResultReturnException("没有权限",403);
        }
        JSONArray files = new JSONArray();
        String lsDirectory = "/home/file"+path;
        if(redisUtils.hasKey("manager:file_tree_"+lsDirectory)){
            files=(JSONArray) redisUtils.get("manager:file_tree_"+lsDirectory);
        }else{
            SSHBean sshBean= new SSHBean();
            sshBean.sshRemoteLogin();
            SSHCache.sshMap.put(UUIDUtil.getUUID(),sshBean);
            Vector lsFiles=sshBean.listFiles(lsDirectory);
//            for(int i=0;i<lsFiles.size();i++){
//                ChannelSftp.LsEntry file=(ChannelSftp.LsEntry)lsFiles.get(i);
//                SftpATTRS attrs=file.getAttrs();
//            }
            files = (JSONArray) JSONArray.toJSON(lsFiles);
            redisUtils.set("manager:file_tree_"+lsDirectory,files);
        }
        return files;
    }

    @RateLimit(limit = 1,timeout = 25000)
    @ApiMapping(value = "downloadFile", title = "下载文件", description = "下载文件")
    public void downloadFile(String filename, HttpServletResponse response) throws Exception {
        SSHBean sshBean= new SSHBean();
        sshBean.sshRemoteLogin();
        SSHCache.sshMap.put(UUIDUtil.getUUID(),sshBean);
        Session session=sshBean.getSession();
        ChannelSftp channelSftp = (ChannelSftp)session.openChannel("sftp");
        channelSftp.connect();
        if(filename.indexOf("/")==0){
            filename=filename.substring(1);
        }
        String lsDirectory = "/home/file/"+filename;
        byte[] fileData = new byte[1024];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        channelSftp.get(lsDirectory, baos);
        fileData = baos.toByteArray();
        if(filename.indexOf("/")!=-1){
            filename=filename.substring(filename.lastIndexOf("/")+1);
        }
        // 设置响应头
        response.setContentType("application/multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;filename="+filename);
        response.setContentLength(fileData.length);

        // 将字节数组写入响应
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(fileData);
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 断开连接
        channelSftp.disconnect();
        session.disconnect();
    }
}
